home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dme / menu.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  8KB  |  390 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  MENU.C
  9.  *
  10.  *  Menu routines... made to take up as little space as possible, and
  11.  *  thus uses many tricks which you should watch out for.
  12.  */
  13.  
  14. #include "defs.h"
  15. #include "graphics/gfxbase.h"
  16. #include "graphics/rastport.h"
  17.  
  18. Prototype void menu_strip (struct Window *);
  19. Prototype void menu_off (void);
  20. Prototype void menu_on (void);
  21. Prototype void do_menuoff (void);
  22. Prototype void do_menuon (void);
  23. Prototype char *menutomacro (char *);
  24. Prototype char *menu_cmd (struct IntuiMessage *);
  25. Prototype void fixmenu (void);
  26. Prototype void do_menuclear (void);
  27. Prototype void do_menuadd (void);
  28. Prototype void do_menudelhdr (void);
  29. Prototype int do_menudel (void);
  30.  
  31. typedef struct {
  32.     ITEM item;
  33.     char *com;
  34. } XITEM;
  35.  
  36. short Menuoff;
  37. short DoMenuoff;
  38.  
  39. MENU *Menu;
  40.  
  41. void
  42. menu_strip(win)
  43. WIN *win;
  44. {
  45.     if (!Menuoff && Menu) {
  46.     SetMenuStrip(win,Menu);
  47.     Forbid();
  48.     win->Flags &= ~RMBTRAP;
  49.     Permit();
  50.     }
  51. }
  52.  
  53. void
  54. menu_off()
  55. {
  56.     ED *ed;
  57.     if (Menuoff == 0) {
  58.     for (ed = (ED *)DBase.mlh_Head; ed->Node.mln_Succ; ed = (ED *)ed->Node.mln_Succ) {
  59.         ClearMenuStrip(ed->Win);
  60.         Forbid();
  61.         ed->Win->Flags |= RMBTRAP;
  62.         Permit();
  63.     }
  64.     }
  65.     ++Menuoff;
  66. }
  67.  
  68. void
  69. menu_on()
  70. {
  71.     ED *ed;
  72.     if (Menu && Menuoff == 1) {
  73.     fixmenu();
  74.     for (ed = (ED *)DBase.mlh_Head; ed->Node.mln_Succ; ed = (ED *)ed->Node.mln_Succ) {
  75.         SetMenuStrip(ed->Win,Menu);
  76.         Forbid();
  77.         ed->Win->Flags &= ~RMBTRAP;
  78.         Permit();
  79.     }
  80.     }
  81.     --Menuoff;
  82. }
  83.  
  84. void
  85. do_menuoff()
  86. {
  87.     menu_off();
  88.     ++DoMenuoff;
  89. }
  90.  
  91. void
  92. do_menuon()
  93. {
  94.     if (DoMenuoff) {
  95.     --DoMenuoff;
  96.     menu_on();
  97.     }
  98. }
  99.  
  100. char *
  101. menutomacro(str)
  102. char *str;
  103. {
  104.     char header[64];
  105.     char itembuf[64];
  106.     short i;
  107.     char *ptr;
  108.     MENU *menu;
  109.     ITEM *item;
  110.  
  111.     for (i = 0; str[i] && str[i] != '-'; ++i);
  112.     if (str[i] == '-') {
  113.     strncpy(header, str, i);
  114.     header[i] = 0;
  115.     strcpy(itembuf, str + i + 1);
  116.     for (menu = Menu; menu; menu = menu->NextMenu) {
  117.         if (ncstrcmp(header, menu->MenuName) == 0) {
  118.         for (item = menu->FirstItem; item; item = item->NextItem) {
  119.             ptr = (char *)((ITEXT *)item->ItemFill)->IText;
  120.             if (ncstrcmp(itembuf, ptr) == 0) {
  121.             ptr = ((XITEM *)item)->com;
  122.             goto done;
  123.             }
  124.         }
  125.         }
  126.     }
  127.     }
  128.     ptr = NULL;
  129. done:
  130.     return(ptr);
  131. }
  132.  
  133. char *
  134. menu_cmd(im)
  135. IMESS *im;
  136. {
  137.     XITEM *item;
  138.  
  139.     if (item = (XITEM *)ItemAddress(Menu, im->Code))
  140.     return(item->com);
  141.     return(NULL);
  142. }
  143.  
  144. /*
  145.  *  new fixmenu by BIX:dhack handles 2.0 fonts
  146.  */
  147.  
  148. void
  149. fixmenu()
  150. {
  151.     MENU *menu;
  152.     ITEM *item;
  153.     ITEXT *it;
  154.     int row, col, maxc, scr;
  155.     struct IntuiText itxt;  /* To find width in case of proportional fonts */
  156.  
  157.     /* Initialize the few elements needed */
  158.     itxt.ITextFont = Ep->Win->WScreen->Font;
  159.     itxt.NextText = NULL;
  160.  
  161.     col = 0;
  162.     for (menu = Menu; menu; menu = menu->NextMenu) {
  163.     short offset;  /* Offset for width; used for position of item
  164.               relative to it's menu header at end of loop */
  165.  
  166.     /* Put this menu header into the IntuiText and figure out how
  167.        wide it is in pixels */
  168.     itxt.IText = menu->MenuName;
  169.     maxc = IntuiTextLength(&itxt);      /* This is now # of pixels */
  170.  
  171.     /* Find 'average' character size */
  172.     offset = (maxc/strlen(menu->MenuName))*2;
  173.     menu->Width = maxc + offset;
  174.  
  175.     row = 0;
  176.     for (item = menu->FirstItem; item; item = item->NextItem) {
  177.         it = (ITEXT *)item->ItemFill;
  178.         item->TopEdge = row;
  179.         if(it != NULL) {
  180.         it->TopEdge = 1;     /* Center in select box */
  181.         it->LeftEdge = offset/2;
  182.         it->DrawMode = JAM1;     /* How workbench's menus are... */
  183.         }
  184.  
  185.         /* Figure out how wide this item is */
  186.         itxt.IText = ((ITEXT *)item->ItemFill)->IText;
  187.         scr = IntuiTextLength(&itxt);  /* This is now # of pixels */
  188.         if (scr > maxc)
  189.         maxc = scr;
  190.  
  191.         /* Figure out how tall the text is */
  192.         if(Ep->Win->WScreen->Font != NULL)
  193.         item->Height = Ep->Win->WScreen->Font->ta_YSize + 2;
  194.  
  195.         else /* This is something to default to, just in case */
  196.         item->Height = GfxBase->DefaultFont->tf_YSize + 2;
  197.  
  198.         row += item->Height;
  199.     }
  200.     maxc += offset;
  201.  
  202.     /* Fit the menu onto the screen */
  203.     if( (maxc+10) > Ep->Win->WScreen->Width ) {   /* Wider than screen! */
  204.         offset = -col;
  205.         /* Unfortunately, this won't reduce the menu's width */
  206.         maxc = Ep->Win->WScreen->Width - 12;
  207.     } else if( (offset = Ep->Win->WScreen->Width - (col+maxc+10)) > 0 )
  208.         offset = 0;
  209.  
  210.     for (item = menu->FirstItem; item; item = item->NextItem) {
  211.         item->Width = maxc;
  212.         item->LeftEdge = offset;
  213.     }
  214.  
  215.     menu->LeftEdge = col;
  216.     menu->Height = row;
  217.     col += menu->Width;
  218.     }
  219. }
  220.  
  221.  
  222. #ifdef NOTDEF
  223. void
  224. fixmenu()
  225. {
  226.     MENU *menu;
  227.     ITEM *item;
  228.     ITEXT *it;
  229.     int row, col, maxc, scr;
  230.  
  231.     col = 0;
  232.     for (menu = Menu; menu; menu = menu->NextMenu) {
  233.     short hdr_width;
  234.     maxc = strlen(menu->MenuName);
  235.     hdr_width = maxc * 8 + 16;
  236.     menu->Width = hdr_width;
  237.     row = 0;
  238.     for (item = menu->FirstItem; item; item = item->NextItem) {
  239.         it = (ITEXT *)item->ItemFill;
  240.         item->TopEdge = row;
  241.         scr = strlen(((ITEXT *)item->ItemFill)->IText);
  242.         if (scr > maxc)
  243.         maxc = scr;
  244.         item->Height = 10;
  245.         row += item->Height;
  246.     }
  247.     maxc = (maxc * 8) + 16;
  248.     for (item = menu->FirstItem; item; item = item->NextItem)
  249.         item->Width = maxc;
  250.     menu->LeftEdge = col;
  251.     menu->Height = row;
  252.     col += hdr_width;
  253.     }
  254. }
  255. #endif
  256.  
  257. /*
  258.  *  menuclear
  259.  *  menuadd    header    item    command
  260.  *  menudel    header    item
  261.  *  menudelhdr    header
  262.  */
  263.  
  264. void
  265. do_menuclear()
  266. {
  267.     menu_off();
  268.     while (Menu) {
  269.     av[1] = (ubyte *)Menu->MenuName;
  270.     do_menudelhdr();
  271.     }
  272.     menu_on();
  273. }
  274.  
  275. void
  276. do_menuadd()
  277. {
  278.     MENU *menu, **mpr;
  279.     ITEM *item, **ipr;
  280.     ITEXT *it;
  281.  
  282.     menu_off();
  283.     mpr = &Menu;
  284.     for (menu = *mpr; menu; menu = *mpr) {
  285.     if (strcmp(av[1], menu->MenuName) == 0) {
  286.         ipr = &menu->FirstItem;
  287.         for (item = *ipr; item; item = *ipr) {
  288.         if (strcmp(av[2], ((ITEXT *)item->ItemFill)->IText) == 0)
  289.             goto newname;
  290.         ipr = &item->NextItem;
  291.         }
  292.         goto newitem;
  293.     }
  294.     mpr = &menu->NextMenu;
  295.     }
  296. newmenu:    /*    create new menu */
  297.     menu = malloc(sizeof(MENU));
  298.     clrmem(menu, sizeof(MENU));
  299.     menu->NextMenu = *mpr;
  300.     *mpr = menu;
  301.     menu->Flags = MENUENABLED;
  302.     menu->MenuName = malloc(strlen(av[1])+1);
  303.     strcpy(menu->MenuName, av[1]);
  304.     ipr = &menu->FirstItem;
  305.     *ipr = NULL;
  306. newitem:    /*    create new item */
  307.     it = malloc(sizeof(ITEXT));
  308.     clrmem(it, sizeof(ITEXT));
  309.     it->BackPen = 1;
  310.     it->DrawMode = JAM2;
  311.     it->IText = malloc(strlen(av[2])+1);
  312.     strcpy(it->IText, av[2]);
  313.     item = malloc(sizeof(XITEM));
  314.     clrmem(item, sizeof(XITEM));
  315.     item->NextItem = *ipr;
  316.     *ipr = item;
  317.     item->ItemFill = (APTR)it;
  318.     item->Flags = ITEMTEXT|ITEMENABLED|HIGHCOMP;
  319. newname:    /*    create new name */
  320.     if (((XITEM *)item)->com)
  321.     free(((XITEM *)item)->com);
  322.     ((XITEM *)item)->com = malloc(strlen(av[3])+1);
  323.     strcpy(((XITEM *)item)->com, av[3]);
  324.     menu_on();
  325. }
  326.  
  327. void
  328. do_menudelhdr()
  329. {
  330.     MENU *menu;
  331.     MENU **mpr;
  332.  
  333.     menu_off();
  334.     mpr = &Menu;
  335.     for (menu = *mpr; menu; menu = *mpr) {
  336.     if (strcmp(av[1], menu->MenuName) == 0) {
  337.         if (menu->FirstItem) {
  338.         while (menu->FirstItem) {
  339.             av[2] = ((ITEXT *)menu->FirstItem->ItemFill)->IText;
  340.             if (do_menudel())
  341.             break;
  342.         }
  343.         break;
  344.         }
  345.         *mpr = menu->NextMenu;
  346.         free(menu->MenuName);
  347.         free(menu);
  348.         break;
  349.     }
  350.     mpr = &menu->NextMenu;
  351.     }
  352.     menu_on();
  353. }
  354.  
  355. int
  356. do_menudel()
  357. {
  358.     MENU *menu;
  359.     ITEM *item, **ipr;
  360.     ITEXT *it;
  361.     short ret = 0;
  362.  
  363.     menu_off();
  364.     for (menu = Menu; menu; menu = menu->NextMenu) {
  365.     if (strcmp(av[1], menu->MenuName) == 0) {
  366.         ipr = &menu->FirstItem;
  367.         for (item = *ipr; item; item = *ipr) {
  368.         it = (ITEXT *)item->ItemFill;
  369.         if (strcmp(av[2], it->IText) == 0) {
  370.             *ipr = item->NextItem;
  371.             free(it->IText);
  372.             free(it);
  373.             free(((XITEM *)item)->com);
  374.             free(item);
  375.             if (!menu->FirstItem) {
  376.             do_menudelhdr();
  377.             ret = 1;
  378.             }
  379.             menu_on();
  380.             return((int)ret);
  381.         }
  382.         ipr = &item->NextItem;
  383.         }
  384.     }
  385.     }
  386.     menu_on();
  387.     return((int)ret);
  388. }
  389.  
  390.